using System;
using System.Collections.Generic;
using System.Text;
using CommonLib;

namespace ImageAlignmentLib
{
    struct MatchResults
    {
        public int x, y;
        public double match;
    }
    
    public class ImageAlignment
    {
        static private int MatchComparer(MatchResults x, MatchResults y)
        {
            if (x.match == y.match)
                return 0;
            else
                if (x.match > y.match)
                {
                    return -1;
                }
            return 1;
        }

        static public Vector FindAlignment(CommonBitmap firstImage, CommonBitmap secondImage)
        {
            Vector result = new Vector();

            // Buscar la mejor coincidencia para un trozo central de la segunda imagen
            int subSetSize = 20; // 1/subSetSize
            CommonBitmap subImageCenter = secondImage.GetSubBitmap(secondImage.Width / 2,
                secondImage.Height / 2, secondImage.Width / subSetSize,
                secondImage.Height / subSetSize, true);

            List<MatchResults> results = new List<MatchResults>();

            for(int x = 0; x < firstImage.Width - subImageCenter.Width; x++)
                for (int y = 0; y < firstImage.Height - subImageCenter.Height; y++)
                {
                    MatchResults m;

                    m.x = x;
                    m.y = y;
                    m.match = CheckMatch(firstImage, subImageCenter, x, y);
                    if (x == 152 && y == 114)
                    {
                        x = 152;
                    }
                    results.Add(m);
                }

            results.Sort(MatchComparer);

            int zx = (results[0].x + subImageCenter.Width / 2) - (firstImage.Width / 2),
                zy = (results[0].y + subImageCenter.Height / 2) - (firstImage.Height / 2);

            result.angle = (180 * Math.Atan2(zy, zx)) / Math.PI;
            result.module = Math.Sqrt((zx * zx) + (zy * zy));

            return result;
        }

        static private double CheckMatch(CommonBitmap mainImage, CommonBitmap subImage, int x, int y)
        {
            int upperBoundX = Math.Min(x + subImage.Width, mainImage.Width),
                upperBoundY = Math.Min(y + subImage.Height, mainImage.Height),
                lowerBoundX = Math.Max(x, 0),
                lowerBoundY = Math.Max(y, 0),
                rx = 0, ry = 0;

            double totalChecks = (upperBoundX - lowerBoundX) * (upperBoundY - lowerBoundY) * 100, actualChecks = 0;

            for (int cx = lowerBoundX; cx < upperBoundX; cx++)
            {
                ry = 0;
                for (int cy = lowerBoundY; cy < upperBoundY; cy++)
                {
                    actualChecks += mainImage.GetPixel(cx, cy).Compare(subImage.GetPixel(rx, ry));
                    ry++;
                }
                rx++;
            }

            return (actualChecks * 100) / totalChecks;
        }
    }
}
